from google.appengine.ext.ndb import msgprop

__author__ = 'Omri'

from google.appengine.ext import ndb
import json
import logging
from protorpc import messages

class RaceStatus(messages.Enum):
    Before = 1
    During = 2
    Finished = 3

class RacerStatus(messages.Enum):
    Ready = 1
    NotReady = 2
    Run = 3
    Finished = 4

class RacePrivacy(messages.Enum):
    Private = 1
    Public = 2

class RaceGenerate(messages.Enum):
    Manual = 1
    Auto = 2

class User(ndb.Model):
    Email = ndb.StringProperty()
    Password = ndb.StringProperty()
    Name = ndb.StringProperty()
    Gender = ndb.StringProperty(choices=["Male","Female"])
    Country = ndb.StringProperty()
    JoinDate = ndb.DateTimeProperty(auto_now_add=True)
    Birthdate = ndb.DateProperty()
    Grade = ndb.IntegerProperty() #TODO: maby should be grade class
    RegID = ndb.StringProperty()
    TotalDistance = ndb.FloatProperty()
    LastRun = ndb.DateProperty()
    BestPlace = ndb.IntegerProperty()

    @property
    def getAbsolutePosition(self):
        return User.query(User.Grade > self.Grade).count() + 1

    @property
    def AverageSpeed(self):
        speed_sum = 0.0;
        historyRaces = RaceHistory.query(RaceHistory.Racer == self.key)
        races_count = historyRaces.count()
        if (races_count):
            for race in historyRaces:
                speed_sum += race.AverageSpeed
            return speed_sum / races_count
        return 0.0

class Race(ndb.Model):
    StartTime = ndb.DateTimeProperty()
    Distance = ndb.FloatProperty()
    Manager = ndb.KeyProperty(kind=User)
    Tags = ndb.StringProperty()
    Participants = ndb.KeyProperty(kind=User, repeated=True)
    ReadyParticipants = ndb.KeyProperty(kind=User, repeated=True)
    Status = msgprop.EnumProperty(RaceStatus) #TODO: newRace, getRaces,
    Privacy = msgprop.EnumProperty(RacePrivacy)
    Generation = msgprop.EnumProperty(RaceGenerate)
    EstimatedTime = ndb.FloatProperty()
    LiveUsersNumber = ndb.IntegerProperty()

    @property
    def NumOfParticipants(self):
        return len(self.Participants)


class CurrentStats(ndb.Model):
    Race = ndb.KeyProperty(kind=Race)
    Racer = ndb.KeyProperty(kind=User)
    Name = ndb.StringProperty()
    Speed = ndb.FloatProperty()
    ActualDistance = ndb.FloatProperty()
    FinishedTime = ndb.DateTimeProperty()
    FinishedPosition = ndb.IntegerProperty()
    Status = msgprop.EnumProperty(RacerStatus) #TODO: ...

    @property
    def RelativePosition(self):
        allParticipants = CurrentStats.query(CurrentStats.Race == self.Race).order(CurrentStats.ActualDistance)
        i = 1
        for stat in allParticipants:
            if stat.Racer == self.Racer: return i

class RaceHistory(ndb.Model):
    Racer = ndb.KeyProperty(kind=User)
    Grade = ndb.IntegerProperty()
    ActualDistance = ndb.FloatProperty()
    FinishedTime = ndb.TimeProperty() #actual running time
    IsFinished = ndb.BooleanProperty()
    Distance = ndb.FloatProperty()
    Position = ndb.IntegerProperty()
    RaceDate = ndb.DateProperty()

    @property
    def AverageSpeed(self):
        total_hours = float(self.FinishedTime.second) / 3600 + float(self.FinishedTime.minute) / 60 + self.FinishedTime.hour
        if total_hours: return self.ActualDistance / total_hours
        return 0.0
